package ui.popup 
{
	import com.*;
	import com.GCQuest;
	import com.Logging.ClientAction;
	import com.Logging.ClientActionType;
	
	import data.*;
	import data.GCQuestData;
	
	import events.GCEvent;
	import events.GCQuestEvent;
	
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.events.TimerEvent;
	import flash.geom.Rectangle;
	import flash.text.TextField;
	import flash.utils.Timer;
	
	import ui.button.GCButton;
	import ui.textfield.GCStylizedText;
	import ui.textfield.GCTextField;
	
	/**
	 * A component representing an NPC
	 * @author Roy
	 */
	public class GCNpcPopup extends GCGoalDisplayObject
	{	
		private var _quantityLeft:int;
		private var _locationText:TextField;

		private var _questArea:Sprite;
		private var _timerArea:Sprite;
		private var _timerText:GCStylizedText;
		private var _turnInButton:GCButton;
		private var _questLabel:GCTextField;
		
		/*
		 * Related to the turn in screen.
		 */
		private var _turnInPopup:GCNpcTurninPopup;
		private var _turnInPopupOpen:Boolean;
		
		/*
		 * Reference to the order.
		 */
		private var _currentOrder:GCQuest;
		
		private var _secondsRemaining:uint;
		private var _countDownTimer:Timer;
		
		/**
		 * Constructor
		 * @param	order
		 */
		public function GCNpcPopup(order:GCQuest) 
		{			
			_currentOrder = order;
			
			_questArea = new Sprite();
			_timerArea = new Sprite();
			_timerText = new GCStylizedText();			
			_turnInButton = new GCButton(onTurnIn);
			_questLabel = new GCTextField();
			
			_turnInPopupOpen = false;
			_turnInPopup = new GCNpcTurninPopup();
			_secondsRemaining = _currentOrder.timeRemaining * 60;
			_countDownTimer = new Timer(1000, 0);
			
			init();
		}
		
		private function init():void
		{
			
			// Add the event listeners for the popup
			_turnInPopup.addEventListener(GCEvent.CONTRIBUTED_NPC_ORDER, onContributed);
			_turnInPopup.addEventListener(GCEvent.POPUP_CLOSED_EVENT, onClosePopup);
			_countDownTimer.addEventListener(TimerEvent.TIMER, onTick);
				
			// Create the quest details clickable
			_questLabel.setStyle(GCTextField.TEXT_TYPE_QUEST);
			_questLabel.height = 50;
			_questLabel.text = "Customer Order"
			//_questName = new TextField();
			//_questName.text = (GCQuestData.getNameFromId(_currentOrder.templateId)) + 012093;
			_questArea.addChild(GCResources.getResource("face"));
			//_questArea.addEventListener(MouseEvent.CLICK, onOpenDetails);
			_questArea.buttonMode = true;
			_questArea.graphics.lineStyle(2, GCConstants.COLOR_GOLD);
			_questArea.graphics.drawRoundRect(0, 0, 100, 100, 20);
			_questArea.addChild(_questLabel);
			
			// Create a timer text box
			_timerText.text = "Time Left:" + _secondsRemaining + " sec";
			_timerText.setBgStyle(GCStylizedText.STYLE_NONE, 150, 30);
			_timerText.setTextStyle(GCTextField.TEXT_TYPE_QUEST);
			_timerArea.addChild(_timerText);
			_timerArea.y = _questLabel.y + _questLabel.height;
			
			// Create the Turn in Button			
			_turnInButton.loadGraphic(GCResources.plate, 100, 30);
			_turnInButton.loadText("Turn In!");
			_turnInButton.width = 100;
			_turnInButton.height = 30;
			
			this.addChild(_questArea);
			if (_secondsRemaining > 0)
				this.addChild(_timerArea);
			this.addChild(_turnInButton);
			
			_turnInButton.y = this.y + this.height - _turnInButton.height;
			_quantityLeft = _currentOrder.goalQuantity - _currentOrder.currentProgress;
			
			// Start the timer for this quest, if time remaining is zero then
			// we assume this quest had no time limit
			if (_secondsRemaining > 0)
			{
				_countDownTimer.start();
			}
		}
		
		override public function cleanUp():void
		{
			
		}
		
		
		//----------------------------------------------------------------------
		//	GET FUNCTIONS
		//----------------------------------------------------------------------
		
		override public function getQuest():GCQuest
		{
			return _currentOrder;
		}
		
		
		//----------------------------------------------------------------------
		//	Event Handlers
		//----------------------------------------------------------------------
		
		
		/**
		 * Opens when the player wants to view the details of an NPC
		 * order.
		 * 
		 * @param	event
		 */
		private function onOpenDetails(event:MouseEvent):void
		{
			var questLocation:String = "Location:" + GCCityData.getNameFromId(_currentOrder.locationId);
			GCQuestData.getDescriptionFromId(_currentOrder.templateId)
			_currentOrder.assignerId;
			var request:String = "The customer requests " + String(_currentOrder.goalQuantity) + " " + GCItemData.getNameFromId(_currentOrder.goalId);
			var reward:String = "Reward: " + String(_currentOrder.rewardAmount) + " ";
			var rewardItemName:String;
			if (_currentOrder.rewardId == GCItemData.ITEM_NULL)
			{
				rewardItemName = "Gold";
			}
			else
			{
				rewardItemName = GCItemData.getNameFromId(_currentOrder.rewardId);
			}
			reward += rewardItemName;
			var progress:String = "Your contribution " + String(_currentOrder.currentProgress);
			var questDesc:String = questLocation + "\n" + request + "\n" + reward + "\n" + progress;
			GCPlayState.disableScreen(new GCTextPopup(questDesc, GCPlayState.enableScreen));
		}
		
		/**
		 * If the player wants to turn in, we must first check that they are in the same
		 * city as specified by the quest
		 * 
		 * @param	event
		 */
		private function onTurnIn(event:MouseEvent):void
		{
			if (GCConstants.LOGGING_DATA)
			{
				var o:Object = new Object();
				o["templateId"] = _currentOrder.templateId;
				o["timeLeft"] = _currentOrder.timeRemaining;
				GCPlayState.logger.LogAction(new ClientAction(ClientActionType.VIEW_NPC_ORDER, o));
			}
			
			var currentCity:GCCity = GCPlayState.getCurrentCity();
			if (currentCity.getId() != _currentOrder.locationId)
			{
				var text:String = this.getQuestDescription() + "\n\nYou must travel to the customer's location to turnin!";
				var popup:GCTextPopup = new GCTextPopup(text , GCPlayState.enableScreen, 300, 400);
				GCPlayState.disableScreen(popup);
				return;
			}
			
			var cityInventory:GCInventory = currentCity._warehouse;
			var shipInventory:GCInventory = GCPlayState.getPlayerInventory();
			var itemId:uint = _currentOrder.goalId;
			var itemOnShip:GCItem = shipInventory.getItemFromId(itemId);
			var amountCanContribute:uint = 0;
			
			if (itemOnShip != null)
			{
				amountCanContribute += itemOnShip.quantity;
			}
			
			if (cityInventory != null && cityInventory.getItemFromId(itemId) != null)
			{
				amountCanContribute += cityInventory.getItemFromId(itemId).quantity;
			}
			
			_turnInPopup.openPopup(_quantityLeft, amountCanContribute, GCItemData.getNameFromId(itemId), getQuestDescription());
			_turnInPopupOpen = true;
			GCPlayState.disableScreen(_turnInPopup);
		}
		
		/**
		 * Triggered when the player decides to contribute resources to an order.
		 * 
		 * @param	event
		 */
		private function onContributed(event:Event):void
		{	
			trace("NPCPopup-- contributed to a quest");
			var quantityToContribute:uint = _turnInPopup.getValue();
			var contributionRemains:uint = quantityToContribute;
			var cityInventory:GCInventory = GCPlayState.getCurrentCity()._warehouse;
			var shipInventory:GCInventory = GCPlayState.getPlayerInventory();
			
			// If contributed nothing then simply exit
			if (quantityToContribute == 0)
			{
				onClosePopup();
				return;
			}
			
			if (GCConstants.LOGGING_DATA)
			{
				var o:Object = new Object();
				o["templateId"] = _currentOrder.templateId;
				o["timeLeft"] = _currentOrder.timeRemaining;
				o["amt"] = quantityToContribute;
				GCPlayState.logger.LogAction(new ClientAction(ClientActionType.CONTR_NPC_ORDER, o));
			}
			
			/*
			 * Remove from ship inventory first. First check that the item type exists
			 */
			var itemAtShip:GCItem = shipInventory.getItemFromId(_currentOrder.goalId);
			if (itemAtShip != null)
			{
				if (itemAtShip.quantity < quantityToContribute)
				{
					/*
					 * If there is not enough in the ship to satisfy the order, we remove
					 * all of it and get the rest from the city.
					 */
					contributionRemains -= itemAtShip.quantity;
					shipInventory.removeFromInventory(_currentOrder.goalId, itemAtShip.quantity);
					
					// DATABASE CALL -- remove turned in goods from ship, all of it
					if (!GCConstants.DEBUG_MODE)
						GCUtil.updateItemQuantity(itemAtShip.invItemId, 0, function(code:uint, data:Object):void { } );
					
				}
				else
				{
					/*
					 * There is enough on the ship
					 */
					contributionRemains = 0;
					shipInventory.removeFromInventory(_currentOrder.goalId, quantityToContribute);
					
					// DATABASE CALL -- remove turned in goods from ship
					if (!GCConstants.DEBUG_MODE)
						GCUtil.updateItemQuantity(itemAtShip.invItemId, itemAtShip.quantity, function(code:uint, data:Object):void { } );
				}
			}
			
			/*
			 * If player had more to contribute, then we move to removing resources from the warehouse.
			 * We know that the player was restricted to contributing resources that were available.
			 */
			if (contributionRemains > 0 && cityInventory != null)
			{
				// Remove item from front-end
				var itemInCity:GCItem = cityInventory.getItemFromId(_currentOrder.goalId);
				var oldItemCityQuantity:uint = itemInCity.quantity;
				cityInventory.removeFromInventory(itemInCity.itemId, contributionRemains);
				
				// The way the DB api is set up, we must account for items on sales as part of the new updated quantity.
				var sales:GCInventory = GCPlayState.getCurrentCity().getSalesFromCity();
				var quantityToChangeTo:uint = oldItemCityQuantity - contributionRemains;
				if (sales != null)
				{
					var saleItem:GCItem = sales.getItemFromId(_currentOrder.goalId);
					if (saleItem != null)
					{
						// Must add up the quantity we have on sale as well
						quantityToChangeTo += saleItem.quantity;
					}
				}
				
				// DATABASE CALL -- remove turned in goods from warehouse
				if (!GCConstants.DEBUG_MODE)
						GCUtil.updateItemQuantity(itemInCity.invItemId, quantityToChangeTo, function(code:uint, data:Object):void { } );
						
				contributionRemains = 0;
			}
			
			/*
			 * Set new progress for this order
			 */
			
			 if (GCConstants.DEBUG_MODE)
			 {
				 setNewQuestProgress();
			 }
			 else
			 {
				 //DATABASE CALL-- contribute to a npc order quest
				GCUtil.updateQuestContribution(_currentOrder.qid, _currentOrder.currentProgress + quantityToContribute, function(code:uint, data:Object):void
				{
					setNewQuestProgress();
				});
			 }
			
			function setNewQuestProgress():void
			{
				_currentOrder.currentProgress += quantityToContribute;
				
				// Change the quantity left
				_quantityLeft = _currentOrder.goalQuantity - _currentOrder.currentProgress;
				
				// Refresh the menus
				dispatchEvent(new Event(GCEvent.REFRESH_MENU_EVENT));
				
				
				if (_currentOrder.isQuestComplete())
				{
					trace("Quest has been completed");
					terminateOrder(true);
					return;
				}
				else
				{
					onClosePopup();
				}
			}
		}
		
		/**
		 * Closes the popup, need to be careful about timing issues, this can be
		 * triggered without the popup being there
		 * 
		 * @param	event
		 */
		private function onClosePopup(event:Event = null):void
		{
			if (_turnInPopupOpen)
			{
				_turnInPopup.closePopup();
				GCPlayState.enableScreen();
				_turnInPopupOpen = false;
			}
		}
		
		/**
		 * Triggered on every tick of the npc timer
		 * 
		 * @param	event
		 */
		private function onTick(event:TimerEvent):void
		{
			_secondsRemaining -= 1;
			_timerText.text = "Time Left:" + _secondsRemaining + " sec";
			
			if (_secondsRemaining % 60 == 0)
			{
				_currentOrder.timeRemaining -= 1;
				
				if (!GCConstants.DEBUG_MODE)
				{
					//DATBASE CALL- updating the number of minutes left in a timed quest
					GCUtil.updateQuestMinLeft(_currentOrder.qid, (_secondsRemaining / 60), function(code:uint, data:Object):void
					{
						trace("Updated number of minutes left in this quest.");
					});
				}
			}
			
			/*
			 * If we reach this point, the order has expired.
			 */
			if (_secondsRemaining == 0)
			{
				terminateOrder(false);
			}
		}
		
		private function terminateOrder(wasSuccess:Boolean):void
		{
			onClosePopup();
			_countDownTimer.stop();
			_countDownTimer.removeEventListener(TimerEvent.TIMER, onTick);
			
			// Dispatch event to notify player that the quest has ended unsuccessfully
			var questEvent:GCQuestEvent = new GCQuestEvent(GCEvent.QUEST_RESOLVED_EVENT);
			questEvent.successfullyCompleted = wasSuccess;
			questEvent.quest = _currentOrder;
			dispatchEvent(questEvent);
		}
		
		private function getQuestDescription():String
		{
			var desctiption:String = "\n\nCustomer Order!\n";
			if (_currentOrder.questType != GCQuestData.QUEST_TYPE_NPCORDER)
				desctiption += GCQuestData.getDescriptionFromId(_currentOrder.templateId);
			var questLocation:String = "Location:" + GCCityData.getNameFromId(_currentOrder.locationId);
			GCQuestData.getDescriptionFromId(_currentOrder.templateId)
			_currentOrder.assignerId;
			var request:String = "The customer requests " + String(_currentOrder.goalQuantity) + " " + GCItemData.getNameFromId(_currentOrder.goalId);
			var reward:String = "Reward " + String(_currentOrder.rewardAmount) + " ";
			var rewardItemName:String;
			if (_currentOrder.rewardId == GCItemData.ITEM_NULL)
			{
				rewardItemName = "Gold";
			}
			else
			{
				rewardItemName = GCItemData.getNameFromId(_currentOrder.rewardId);
			}
			reward += rewardItemName;
			var progress:String = "Your contribution " + String(_currentOrder.currentProgress);
			var questDesc:String = desctiption + "\n\n" + questLocation + "\n\n" + request + "\n\n" + reward + "\n\n" + progress;
			
			return questDesc;
		}
	}
}